home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / hexed.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  9KB  |  396 lines

  1. /*
  2.  * Hexidecimal screen editor:
  3.  * NOTE: Must be compiled in SMALL model!
  4.  *
  5.  *    Special Keys:
  6.  *        PgDn        = Page forward
  7.  *        PgUp        = Page backward
  8.  *        CTRL-PgUp    = Goto start of file
  9.  *        CTRL-PgDn    = Goto end of file
  10.  *        Home        = Goto start of line
  11.  *        End            = Goto end of line
  12.  *        Ins            = Insert a byte at cursor location
  13.  *        Del            = Delete a byte at cursor location
  14.  *        F1            = Toggle between HEX/ASCII editing
  15.  *        CTRL-Home    = Redraw screen
  16.  *    F10/Keypad '+'    = Enter command
  17.  *     F9/Keypad '-'    = Re-execute last command
  18.  *    Commands:
  19.  *        G<xxxx>        = Goto address xxxx
  20.  *        Q            = Quit editor
  21.  *        QQ            = Quit even if unsaved changes
  22.  *        W[file]        = Write file
  23.  *        X[file]        = Exit and write file
  24.  *        ?xx ...        = Search for HEX byte pattern
  25.  *        /text...    = Search for ASCII text
  26.  *
  27.  * Copyright 1983-1994 Dave Dunfield
  28.  * All rights reserved
  29.  *
  30.  * Permission granted for personal (non-commercial) use only.
  31.  *
  32.  * Compile command: cc hexed -fops
  33.  */
  34. #include <stdio.h>
  35. #include <video.h>
  36. #include <file.h>
  37.  
  38. #define ALLOCATION    60001
  39.  
  40.     char cmdbuf[50], *cmdptr, searchbuf[50];
  41.     /* Declare data buffer in two chunks, to prevent a negative size,
  42.        which confuses MASM */
  43.     unsigned char data[ALLOCATION/2], data1[ALLOCATION/2];
  44.  
  45. /*
  46.  * Skip to the next non-blank character
  47.  */
  48. char skip()
  49. {
  50.     while(*cmdptr == ' ')
  51.         ++cmdptr;
  52.     return *cmdptr;
  53. }
  54.  
  55. main(argc, argv)
  56.     unsigned argc;
  57.     char *argv[];
  58.  
  59. {
  60.     int cursor;
  61.     unsigned i, j, k, pos, size;
  62.     unsigned char c, chr, mode, modified;
  63.     HANDLE fh;
  64.  
  65.     cursor = pos = mode = modified = 0;
  66.     if(argc<2)
  67.         abort("\nUse: hexed <file>\n\nCopyright 1983-1994 Dave Dunfield\nAll rights reserved.\n");
  68.  
  69.     
  70.     if(!(fh=open(argv[1], F_READ)))
  71.         abort("HEXED: Cannot open input file\n");
  72.  
  73.     if((size = read(data, ALLOCATION, fh)) >= ALLOCATION)
  74.         abort("HEXED: File to large\n");
  75.  
  76.     close(fh);
  77.  
  78.     vopen();
  79.  
  80. draw:        /* draw entire screen */
  81.     vgotoxy(0,0);
  82.     for(i=0; i<30; ++i) vputc('-');
  83.     V_ATTR = REVERSE;
  84.     putstr(" Hex-Ed Version 1.3 ");
  85.     V_ATTR = NORMAL;
  86.     for(i=0; i<30; ++i) vputc('-');
  87.     vgotoxy(0,2);
  88.     vprintf("File: %s",argv[1]);
  89.     vgotoxy(59,2);
  90.     vprintf("Size: %u, ($%04x)",size, size);
  91.  
  92. redraw:        /* re-draw text area of screen */
  93.     for(i=0; i < 16; ++i) {        /* for each line */
  94.         vgotoxy(0, i+4);
  95.         if(size <= (k=pos+(i*16)))
  96.             break;
  97.         vprintf("%04x  ",k=pos+(i*16));
  98.         for(j = k; j < (k+16) ; ++j) {
  99.             if(j<size)
  100.                 vprintf(" %02x", data[j]);
  101.             else {
  102.                 vcleol();
  103.                 break; } }
  104.         vgotoxy(63,i+4);
  105.         for(j = k; (j<(k+16)) && (j<size); ++j)
  106.             putprint(data[j]); }
  107.     vcleos();
  108.  
  109. prompt:
  110.     if(mode)
  111.         vgotoxy(63 + cursor%16, 4 + cursor/16);
  112.     else
  113.         vgotoxy(7+3*(cursor%16), 4+cursor/16);
  114.     switch(chr = vgetc()) {
  115.         case _KUA :        /* backup a line (16 bytes) */
  116.             if((cursor = cursor - 16) < 0) {
  117.                 cursor += 16;
  118.         case _KPU :        /* backup a page (256 bytes) */
  119.             if(pos > 255) {
  120.                 pos -= 256;
  121.                 goto redraw; }
  122.             else if(pos) {
  123.                 pos = 0;
  124.                 goto redraw; } }
  125.             break;
  126.         case _KDA :        /* advance a line (16 bytes) */
  127.             if((cursor + pos + 16) >= size)
  128.                 break;
  129.             if(cursor <= (255-16)) {
  130.                 cursor += 16;
  131.                 break; }
  132.         case _KPD :        /* advance a page (256 bytes) */
  133.             if((pos+256) < size)
  134.                 pos += 256;
  135.             if((pos + cursor) > size)
  136.                 cursor = size - pos - 1 ;
  137.             goto redraw;
  138.         case _KLA :        /* backup one byte */
  139.             if(cursor)
  140.                 --cursor;
  141.             else if(pos) {
  142.                 --pos;
  143.                 goto redraw; }
  144.             break;
  145.         case _KRA :        /* advance one byte */
  146.             if(size <= (pos + ++cursor)) --cursor;
  147.             else if(255 < cursor) {
  148.                 --cursor;
  149.                 if(pos < (size - 255)) ++pos;
  150.                 goto redraw; }
  151.             break;
  152.         case _CPD :        /* goto end of file */
  153.             if(size > 255) {
  154.                 cursor = 255;
  155.                 pos = size - 256; }
  156.             else {
  157.                 cursor = size-1;
  158.                 pos = 0; }
  159.             goto redraw;
  160.         case _CPU :        /* goto start of file */
  161.             cursor = pos = 0;
  162.             goto redraw;
  163.         case _KEN :        /* advance to end of field */
  164.             cursor = (cursor & 0xff0) + 15;
  165.             if(size <= cursor+pos)
  166.                 cursor = size - pos - 1;
  167.             break;
  168.         case _KHO :        /* backup to beginning of field */
  169.             cursor = cursor & 0xff0;
  170.             break;
  171.         case _K1 :        /* swap editing field */
  172.             mode = ~mode;
  173.             break;
  174.         case _CHO :        /* re-draw the screen */
  175.             vclscr();
  176.             goto draw;
  177.         case _KDL:        /* Delete a byte */
  178.             i = pos + cursor;
  179.             while(i < size)
  180.                 data[i] = data[++i];
  181.             if((pos + cursor) >= --size) {
  182.                 if(cursor)
  183.                     --cursor;
  184.                 else if(pos)
  185.                     --pos; }
  186.             modified = -1;
  187.             goto redraw;
  188.         case _KIN:        /* Insert a byte */
  189.             i = pos + cursor;
  190.             if(size < ALLOCATION) {
  191.                 chr = data[i];
  192.                 while(i < size) {
  193.                     c = data[++i];
  194.                     data[i] = chr;
  195.                     chr = c; }
  196.                 ++size; }
  197.             modified = -1;
  198.             goto redraw;
  199.         case _K10 :        /* execute line mode command */
  200.         case _KKP :
  201.             vgotoxy(0,22);
  202.             vcleos();
  203.             vputs("Command: ");
  204.             i = 0;
  205.             do {
  206.                 if((chr = vgetc()) == _KBS) {
  207.                     if (i) {
  208.                         putstr("\010 \010");
  209.                         --i; } }
  210.                 else if(chr < 128)
  211.                     vputc(cmdbuf[i++] = chr); }
  212.             while((chr != _KKP) && (chr != _K10));
  213.             cmdbuf[i] = 0;
  214.         case _K9 :        /* repeat last command */
  215.         case _KKM :
  216.             vgotoxy(0, 22);
  217.             V_ATTR = REVERSE;
  218.             putstr(cmdbuf);
  219.             V_ATTR = NORMAL;
  220.             vcleos();
  221.             cmdptr = cmdbuf;
  222.             switch(chr = toupper(skip())) {
  223.                 case 'G' :        /* goto address */
  224.                     ++cmdptr;
  225.                     skip();
  226.                     i = 0;
  227.                     if((i = gethex()) == -1)
  228.                         break;
  229.                     cursor = 0;
  230.                     pos = (i<size) ? i : size;
  231.                     goto redraw;
  232.                 case '/' :        /* Search for ASCII */
  233.                     i = 0;
  234.                     while(*++cmdptr)
  235.                         searchbuf[i++] = *cmdptr;
  236.                     if(!i)
  237.                         break;;
  238.                     goto do_search;
  239.                 case '?' :        /* search for HEX */
  240.                     ++cmdptr;
  241.                     skip();
  242.                     i = 0;
  243.                     do
  244.                         searchbuf[i++] = j = gethex();
  245.                     while((j != -1) && skip());
  246.                     if(j == -1)
  247.                         break;
  248.         do_search:    j = pos + cursor + 1;
  249.                     while(!compare(searchbuf, data+j, i)) {
  250.                         if(++j >= size) {
  251.                             error("Not found");
  252.                             break; } }
  253.                     if(j < size) {
  254.                         if((cursor = j - pos) & 0xff00) {
  255.                             pos = j;
  256.                             cursor = 0;
  257.                             goto redraw; } }
  258.                     break;
  259.                 case 'X' :        /* Exit and write file */
  260.                 case 'W' :        /* write file */
  261.                     ++cmdptr;
  262.                     if(!skip())
  263.                         cmdptr = argv[1];
  264.                     if(fh=open(cmdptr, F_WRITE)) {
  265.                         write(data, size, fh);
  266.                         modified = 0;
  267.                         close(fh); }
  268.                     else {
  269.                         error("Can't open output file");
  270.                         break; }
  271.                     if(chr != 'X')
  272.                         break;
  273.                 case 'Q' :        /* quit (Exit) */
  274.                     if(modified && (toupper(*(cmdptr+1)) != 'Q'))
  275.                         error("Unsaved changes, 'qq' to quit anyway");
  276.                     else {
  277.                         vclscr();
  278.                         exit(0); }
  279.                     break;
  280.                 case 0 :        /* null command, do nothing */
  281.                     break;
  282.                 default:
  283.                     error("Unknown command"); }
  284.             vgotoxy(0,22);
  285.             vcleol();
  286.             break;
  287.         default:
  288.             k = data[pos + cursor];
  289.             if(mode) {
  290.                 data[pos+cursor] = k = chr;
  291.                 chr = modified = -1; }
  292.             else {
  293.                 if(ishex(chr = toupper(chr))) {
  294.                     vputc(chr);
  295.                     if(chr > '9') chr -= 7;
  296.                     i = (chr-'0')*16;
  297.                     vputc('-');
  298.                     vputc('\b');
  299.                     if(ishex(chr=toupper(vgetc()))) {
  300.                         if(chr > '9') chr -= 7;
  301.                         data[pos+cursor] = k =(chr-'0') + i;
  302.                         chr = modified = -1; } } }
  303.                 vgotoxy(7+3*(cursor%16), 4+cursor/16);
  304.                 vprintf("%02x ",k);
  305.                 vgotoxy(63 + cursor%16, 4 + cursor/16);
  306.                 putprint(k);
  307.                 if(chr == -1) {
  308.                     if(size <= (pos + ++cursor)) --cursor;
  309.                     else if(cursor > 255) {
  310.                         if(pos < (size-256)) {
  311.                             pos += 256;
  312.                             cursor = 0; }
  313.                         else 
  314.                             pos = size-(pos + cursor);
  315.                     goto redraw; } } }
  316.     goto prompt;
  317. }
  318.  
  319. /*
  320.  * Test for a valid hexidecimal digit
  321.  */
  322. ishex(chr)
  323.     char chr;
  324. {
  325.     return ((chr >= '0') && (chr <= '9')) || ((chr >= 'A') && (chr <= 'F'));
  326. }
  327.  
  328. /*
  329.  * Get a hex value from the input line
  330.  */
  331. gethex()
  332. {
  333.     register unsigned i;
  334.     register char chr, flag;
  335.  
  336.     flag = i = 0;
  337.     while(ishex(chr = toupper(*cmdptr))) {
  338.         ++cmdptr;
  339.         flag = -1;
  340.         if(chr > '9')
  341.             chr -= 7;
  342.         i = (i*16) + (chr - '0'); }
  343.     if(!flag) {
  344.         error("Invalid HEX digit");
  345.         return -1; }
  346.     return i;
  347. }
  348.  
  349. /*
  350.  * Dis